package com.boot.cluster;

import com.boot.cluster.listener.GroupMemberListener;
import com.boot.cluster.listener.MessageReceiverListener;
import com.boot.cluster.model.MessageInfo;
import com.boot.cluster.utils.HessianSerializer;
import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.raft.RaftHandle;

import java.io.Closeable;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractClusterClient implements Closeable {

		public static String BIND_HOST_PARAM_NAME = "bind_addr";//NOPMD
	protected JChannel channel;
	protected ClusterConfig config;
	protected List<MessageReceiverListener> receiverListeners;

	protected GroupMemberListener memberListener;

	protected RaftHandle raft;

	public abstract void init();

	public ClusterConfig getConfig() {
		return this.config;
	}

	public void setConfig(ClusterConfig config) {
		this.config = config;
	}

	@Override
	public void close() {
		if (this.channel != null) {
			this.channel.close();
		}
	}

	/**
	 * 群发消息
	 *
	 * @param o
	 */
	public void send(MessageInfo<?> o) {
		if (o == null) {
			return;
		}
		try {
			this.channel.send(new Message(null, HessianSerializer.serialize(o)));
		} catch (Exception e) {
			throw new RuntimeException("send error", e);
		}
	}

	/**
	 * 消息发送到指定节点上
	 *
	 * @param target
	 * @param o
	 */
	public void send(Address target, MessageInfo<?> o) {
		if (o == null) {
			return;
		}
		if (target == null) {
			this.send(o);
			return;
		}
		try {
			this.channel.send(new Message(target, HessianSerializer.serialize(o)));
		} catch (Exception e) {
			throw new RuntimeException("send error", e);
		}
	}
	public void addReceiverListener(MessageReceiverListener Handle) {
		if(Handle.getType()==null) {
			throw new IllegalArgumentException("Listener not specified type");
		}
		if(this.receiverListeners==null) {
			this.receiverListeners=new ArrayList<>();
		}
		this.receiverListeners.add(Handle);
	}


	public void setMemberListener(GroupMemberListener Handle) {
		this.memberListener = Handle;
	}

	public boolean isLeader() {
		if (this.raft == null) {
			return false;
		}
		return this.raft.isLeader();
	}

	public Address getLeader() {
		return this.raft.leader();
	}

	public List<MessageReceiverListener> getMessageReceiverListener(){
		return this.receiverListeners;
	}

	public GroupMemberListener getGroupMemberListener() {
		return this.memberListener ;
	}

}
